package it.uni.bo.monitoring.sla.chain.availability;

import it.uni.bo.monitoring.protocol.unmarshaller.EventInfo;
import it.uni.bo.monitoring.sla.context.AutomataState;
import it.uni.bo.monitoring.sla.context.AutomataTransition;
import it.uni.bo.monitoring.sla.context.ComponentManager;

import java.util.Vector;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;

import static it.uni.bo.monitoring.service.StaticFields.QUERY_SQL_VIOLATION;

public class ReliabilityManager implements ComponentManager{
	private AutomataState init_st;
	private AutomataState end_st;
	private AutomataState cur_st;
	private Vector<Long> t;
	private int cur_index,count;
	private int numStates;
	//private Vector<AutomataTransition> transitions; // Vector of Transition object
	private long xreal;
	private SessionFactory factory;
	private Logger l;
	private String description;
	private final static String DESC_VIOLATION="RELIABILITY";
	

	public ReliabilityManager(int numStates, AutomataState init_st, AutomataState end_st, SessionFactory factory) {
		l = Logger.getLogger(this.getClass());
		this.init_st = init_st;
		this.end_st = end_st;
		cur_st = null;
		this.numStates=numStates;
		t = new Vector<Long>();
		cur_index = 0;
		count = 0;
		xreal = 0;
	//	transitions= new Vector<AutomataTransition>();
		this.factory=factory;
		//	l.debug("AUTOMA: numStates-"+numStates+" init_st-"+init_st+" end_st-"+end_st);
	}
/*
	public void addTransition(AutomataTransition t) {
		transitions.addElement(t);
		//	t.printTransition();
	}
*/

	public void makeTrans(EventInfo ei) {
		//filtro le prime count richieste
		if ( count < (numStates-1)) {
			t.add(ei.getTimestamp());
			count++;
		} else {
			t.set(cur_index,ei.getTimestamp());
			cur_index++;
			if ( cur_index == (numStates-1))
				cur_index = 0;
		}
		if ( count >= (numStates-1)) {
			int myplace = cur_index;
			for (int i=0; i < (numStates-1); i++ ) {
				int whichone = (myplace+i) % (numStates-1);
				description=DESC_VIOLATION+ " | "+ei.getAppUrl()+ " | "+ei.getNamespace()+ " | "+ei.getOperationName()+" | ";
				int res = intMakeTrans((t.elementAt(whichone)));
				if ( res == 1 ) {
					l.info(description);
					if(factory!=null){
						Session session=factory.openSession();
						Query query = session.createSQLQuery(QUERY_SQL_VIOLATION);
						query.setString(0, "reliability");
						query.setLong(1, ei.getIdSla());
						query.setBinary(2, ei.getIdE());
						query.setString(3, description);
						l.info("Hibernate: "+QUERY_SQL_VIOLATION+" [ reliability "+ei.getIdSla()+" "+new String(ei.getIdE())+" "+description+" ]");
						query.executeUpdate();
						if ((session!=null) && (session.isOpen())) 
							session.close(); 
					}
				}

			}
		}
	}

	public int intMakeTrans(long time) {
		boolean done = false;
		long x = time - xreal;

		if ( cur_st == null )
			cur_st = init_st;

		AutomataTransition t = cur_st.getTransition("");
		if (t!=null){
			if((t.getGuard() <=0) || ((t.getGuard() >0) && (x < t.getGuard()) && (x!=0))) {
				if(t.getGuard() >0)
					description+="Difference= ("+time +"-"+xreal+") = "+x+" < "+t.getGuard();
				done = true;
				if (cur_st.equals(init_st)) 
					xreal = time;
				cur_st = t.getTarget(); 
			}
		}
		if ( cur_st.equals(end_st) ) { 
			cur_st = null;
			return 1;
		}
		if ( done == false ) {
			cur_st = null;
			xreal = 0;
			return -1;
		}
		return 0;
	}

}
